home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / AppsToGo / DTS.Lib / PICTControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  13.6 KB  |  590 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         pictcontrol.c
  5. ** Written by:      Eric Soldan
  6. **
  7. ** Copyright © 1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19.  
  20.  
  21. /*****************************************************************************/
  22.  
  23.  
  24.  
  25. #ifndef __PICTCONTROL__
  26. #include "PICTControl.h"
  27. #endif
  28.  
  29. #ifndef __CONTROLS__
  30. #include <Controls.h>
  31. #endif
  32.  
  33. #ifndef __DTSLib__
  34. #include "DTS.Lib.h"
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __FONTS__
  42. #include <Fonts.h>
  43. #endif
  44.  
  45. #ifndef __GWLAYERS__
  46. #include "GWLayers.h"
  47. #endif
  48.  
  49. #ifndef __MEMORY__
  50. #include <Memory.h>
  51. #endif
  52.  
  53. #ifndef __PACKAGES__
  54. #include <Packages.h>
  55. #endif
  56.  
  57. #ifndef __RESOURCES__
  58. #include <Resources.h>
  59. #endif
  60.  
  61. #ifndef __STRINGUTILS__
  62. #include "StringUtils.h"
  63. #endif
  64.  
  65. #ifndef __UTILITIES__
  66. #include "Utilities.h"
  67. #endif
  68.  
  69.  
  70.  
  71. /*****************************************************************************/
  72.  
  73.  
  74.  
  75. #ifdef powerc
  76. #pragma options align=mac68k
  77. #endif
  78. typedef struct cdefRsrcJMP {
  79.     long    jsrInst;
  80.     long    moveInst;
  81.     short    jmpInst;
  82.     long    jmpAddress;
  83. } cdefRsrcJMP;
  84. typedef cdefRsrcJMP *cdefRsrcJMPPtr, **cdefRsrcJMPHndl;
  85. #ifdef powerc
  86. #pragma options align=reset
  87. #endif
  88.  
  89.  
  90.  
  91. /*****************************************************************************/
  92.  
  93.  
  94.  
  95. short    gPICTCtl = rPICTCtl;
  96.  
  97. extern ControlHandle    gWhichCtlHit;
  98. extern Boolean            gWhichCtlDbl;
  99. extern Boolean            gWhichCtlTracking;
  100.  
  101. static pascal long        CPICTCtl   (short varCode, ControlHandle ctl, short msg, long parm);
  102. static pascal void        CPICTAction(ControlHandle ctl, short part);
  103. static pascal void        NoRect(GrafVerb verb, Rect *r);
  104. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id);
  105.  
  106. static cdefRsrcJMPHndl    gCDEF;
  107.  
  108.  
  109.  
  110. /*****************************************************************************/
  111. /*****************************************************************************/
  112.  
  113. #ifdef applec
  114. #pragma segment ATGControls
  115. #endif
  116.  
  117. /*****************************************************************************/
  118. /*****************************************************************************/
  119.  
  120.  
  121.  
  122. static pascal long    CPICTCtl(short varCode, ControlHandle ctl, short msg, long parm)
  123. {
  124.     Rect                viewRct, r;
  125.     short                thisHilite, keepHilite, i;
  126.     unsigned long        resPICTID, id, variant, sticky, offScreen, srcOrMode;
  127.     PicHandle            pict;
  128.     ControlHandle        cc;
  129.     WindowPtr            ww, curPort, keepPort;
  130.     LayerObj            wlayer, blayer;
  131.     RgnHandle            oldClip, newClip, colorRgn;
  132.     short                txFont, txSize, txMode, fnum, depth;
  133.     Style                txFace;
  134.     QDProcs                qdp;
  135.     QDProcsPtr            oldqdp;
  136.     FontInfo            finfo;
  137.     ControlStyleInfo    cinfo;
  138.     char                hstate;
  139.     Handle                dh;
  140.     Str255                str;
  141.  
  142.     static QDRectUPP    qdrupp;
  143.  
  144.     viewRct    = (*ctl)->contrlRect;
  145.     thisHilite = (*ctl)->contrlHilite;
  146.     resPICTID  = (*ctl)->contrlRfCon & 0x0000FFFFL;
  147.     variant    = (*ctl)->contrlRfCon & 0xFFFF0000L;
  148.     sticky     = variant & 0x00010000L;
  149.     offScreen  = variant & 0x00020000L;
  150.     srcOrMode  = variant & 0x00080000L;
  151.  
  152.     switch (msg) {
  153.  
  154.         case drawCntl:
  155.  
  156.             pcpy(str, (*ctl)->contrlTitle);
  157.  
  158.             GetPort(&curPort);
  159.             if (EmptyRgn(curPort->visRgn)) offScreen = 0;
  160.                 /* We are fully clipped out, so there's no sense in going offscreen.
  161.                 ** The only reason that we don't just leave is that the application
  162.                 ** may have set up this condition with the expectation of contributing
  163.                 ** the control into a PICT. */
  164.  
  165.             if (offScreen) {
  166.                 NewLayer(&wlayer, nil, nil, curPort, 0, 0);
  167.                 if (srcOrMode) (*wlayer)->xferMode = srcOr;
  168.                 r = curPort->portRect;
  169.                 SectRect(&r, &viewRct, &r);
  170.                 (*wlayer)->dstRect = r;                /* Minimize the size of the offscreen. */
  171.                 depth = (*ctl)->contrlMin;
  172.                 if (depth < 0) {
  173.                     depth = -depth;
  174.                     depth &= 0xFF;
  175.                 }
  176.                 NewLayer(&blayer, wlayer, nil, nil, depth, 0);
  177.                 SetLayerWorld(blayer);
  178.                 InvalLayer(wlayer, r, false);
  179.             }
  180.  
  181.             if (sticky) {
  182.                 if (thisHilite < 2)
  183.                     thisHilite = (*ctl)->contrlValue;
  184.                 if (thisHilite == 2)
  185.                     thisHilite = 255;
  186.             }
  187.  
  188.             switch (thisHilite) {
  189.                 case 1:
  190.                 case 255:
  191.                     id = (thisHilite == 1) ? (resPICTID + 2) : (resPICTID + 4);
  192.  
  193.                     SetResLoad(false);
  194.                     if (!GetPICT(ctl, resPICTID, id)) id = resPICTID;
  195.                     SetResLoad(true);
  196.  
  197.                     (*ctl)->contrlRfCon = (id + variant - offScreen);    /* Prevent nesting of offscreen. */
  198.                     keepHilite = (*ctl)->contrlHilite;
  199.                     (*ctl)->contrlHilite = 99;
  200.                     CPICTCtl(varCode, ctl, msg, parm);
  201.                     str[0] = 0;                                            /* Just draw the text once. */
  202.                     (*ctl)->contrlHilite = keepHilite;
  203.                     (*ctl)->contrlRfCon  = (resPICTID | variant);
  204.                     if (thisHilite == 1)
  205.                         if (id == resPICTID)
  206.                             InvertRect(&viewRct);
  207.                                 /* If there is no hilite==1 'PICT', invert the base 'PICT'. */
  208.                     break;
  209.                 default:
  210.                     if (!(variant & 0x01)) resPICTID += (*ctl)->contrlValue;
  211.  
  212.                     EraseRect(&viewRct);        /* Start pict fresh and clean. */
  213.  
  214.                     pict = GetPICT(ctl, resPICTID, resPICTID);
  215.                     if (!pict) {
  216.                         FrameRect(&viewRct);
  217.                         break;
  218.                     }
  219.  
  220.                     hstate = HGetState((Handle)pict);        /* Lock it before moving something */
  221.                     HLock((Handle)pict);                    /* causes it to purge.               */
  222.  
  223.                     GetPort(&keepPort);
  224.                     SetPort((*ctl)->contrlOwner);
  225.                     depth = 4;
  226.                     if ((*ctl)->contrlMin < 0) {
  227.                         depth = -(*ctl)->contrlMin;
  228.                         if (depth & 0xFF00)
  229.                             depth >>= 8;
  230.                         else
  231.                             depth  &= 0xFF;
  232.                     }
  233.                     colorRgn = LocalScreenDepthRegion(depth);
  234.                     SetPort(keepPort);
  235.  
  236.                     oldClip = NewRgn();
  237.                     newClip = NewRgn();
  238.                     GetClip(oldClip);            /* Draw color area first. */
  239.                     RectRgn(newClip, &curPort->portRect);
  240.                     SectRgn(newClip, colorRgn, newClip);
  241.                     SetClip(newClip);
  242.                     DrawPicture(pict, &viewRct);
  243.                     HSetState((Handle)pict, hstate);
  244.  
  245.                     pict = GetPICT(ctl, resPICTID, resPICTID + 1);
  246.                     if (!pict)
  247.                         pict = GetPICT(ctl, resPICTID, resPICTID);
  248.                     if (pict) {
  249.                         hstate = HGetState((Handle)pict);
  250.                         HLock((Handle)pict);
  251.                         RectRgn(newClip, &curPort->portRect);    /* Draw b/w pict area. */
  252.                         DiffRgn(newClip, colorRgn, newClip);
  253.                         SetClip(newClip);
  254.                         DrawPicture(pict, &viewRct);
  255.                         HSetState((Handle)pict, hstate);
  256.                     }
  257.  
  258.                     SetClip(oldClip);
  259.                     DisposeRgn(oldClip);
  260.                     DisposeRgn(newClip);
  261.                     DisposeRgn(colorRgn);
  262.  
  263.                     break;
  264.             }
  265.  
  266.             if (str[0]) {
  267.                 GetPort(&ww);
  268.                 txFont = ww->txFont;
  269.                 txFace = ww->txFace;
  270.                 txSize = ww->txSize;
  271.                 if (!((variant >> 16) & useWFont)) {
  272.                     TextFont(systemFont);
  273.                     TextFace(normal);
  274.                     TextSize(0);
  275.                 }
  276.                 else {
  277.                     if (GetControlStyle(ctl, &cinfo)) {
  278.                         TextFace(cinfo.fontStyle);
  279.                         fnum = systemFont;
  280.                         if (cinfo.font[0])
  281.                             GetFNum(cinfo.font, &fnum);
  282.                         TextFont(fnum);
  283.                         TextSize(cinfo.fontSize);
  284.                     }
  285.                 }
  286.  
  287.                 oldqdp = ww->grafProcs;
  288.                 if (oldqdp)
  289.                     BlockMove(oldqdp, &qdp, sizeof(QDProcs));
  290.                 else
  291.                     SetStdProcs(&qdp);
  292.                 if (!qdrupp) {
  293. #if USES68KINLINES
  294.                     qdrupp = (QDRectUPP)NoRect;
  295. #else
  296.                     qdrupp = NewQDRectProc(NoRect);
  297. #endif
  298.                 }
  299.                 qdp.rectProc = qdrupp;
  300.                 ww->grafProcs = &qdp;
  301.                 txMode = ww->txMode;
  302.                 TextMode(srcOr);
  303.  
  304.                 GetFontInfo(&finfo);
  305.                 viewRct.top += (finfo.ascent + finfo.descent) / 2;
  306.                 if (viewRct.top < viewRct.bottom)
  307.                     TETextBox(str + 1, str[0], &viewRct, teCenter);
  308.  
  309.                 ww->grafProcs = oldqdp;
  310.                 TextMode(txMode);
  311.  
  312.                 TextFont(txFont);
  313.                 TextFace(txFace);
  314.                 TextSize(txSize);
  315.             }
  316.  
  317.             if (offScreen) {
  318.                 UpdateLayer(wlayer);
  319.                 ResetLayerWorld(blayer);
  320.                 DisposeThisAndBelowLayers(wlayer);
  321.             }
  322.  
  323.             break;
  324.  
  325.         case testCntl:
  326.  
  327.             if ((*ctl)->contrlHilite == 255) return(0);
  328.                 /* Control disabled, so no click.  (We probably don't get called in this case. */
  329.  
  330.             if (!sticky) return(PtInRect(*(Point *)&parm, &viewRct));
  331.                 /* Don't make user call WhichControl unless the variant
  332.                 ** is for double-clicking.  (Then it has to be called.) */
  333.  
  334.             if (ctl != gWhichCtlHit) return(0);
  335.                 /* WhichControl already found the control hit.  Unless it is the one
  336.                 ** found by WhichControl, consider it unhit. */
  337.  
  338.             if (gWhichCtlTracking) return(1);
  339.                 /* We already handled it, but the control manager is insistent. */
  340.  
  341.             if (!(*ctl)->contrlValue) {            /* Turn off any other controls in this family. */
  342.                 ww = (*ctl)->contrlOwner;
  343.                 for (cc = nil; (cc = CPICTNext(ww, cc, 1, true)) != nil;) {
  344.                     if (cc != ctl) {
  345.                         if (((*cc)->contrlMax & 0xFFF0) == ((*ctl)->contrlMax & 0xFFF0)) {
  346.                             if ((*cc)->contrlValue) {
  347.                                 (*cc)->contrlValue  = 0;
  348.                                 (*cc)->contrlHilite = 0;
  349.                                 CPICTCtl(varCode, cc, drawCntl, 0);
  350.                             }
  351.                         }
  352.                     }
  353.                 }
  354.             }
  355.  
  356.             (*ctl)->contrlValue = 1;
  357.             if (gWhichCtlDbl)                        /* If user double-clicked... */
  358.                 if (!((*ctl)->contrlMax & 0x01))    /* If double-clicking allowed... */
  359.                     (*ctl)->contrlValue = 2;
  360.  
  361.             CPICTCtl(varCode, ctl, drawCntl, 0);
  362.  
  363.             gWhichCtlTracking = true;
  364.             return(1);
  365.  
  366.             break;
  367.  
  368.         case calcCRgns:
  369.         case calcCntlRgn:
  370.             if (msg == calcCRgns)
  371.                 parm &= 0x00FFFFFF;
  372.             RectRgn((RgnHandle)parm, &viewRct);
  373.             break;
  374.  
  375.         case initCntl:
  376.             (*ctl)->contrlData = nil;
  377.             break;
  378.  
  379.         case dispCntl:
  380.             dh = (*ctl)->contrlData;
  381.             if (dh) {
  382.                 for (i = 0; i < 6; ++i) {
  383.                     pict = (*(PicHandle **)dh)[i];
  384.                     if (pict) KillPicture(pict);
  385.                 }
  386.                 DisposeHandle(dh);
  387.                 (*ctl)->contrlData = nil;
  388.             }
  389.             break;
  390.  
  391.         case posCntl:
  392.             break;
  393.  
  394.         case thumbCntl:
  395.             break;
  396.  
  397.         case dragCntl:
  398.             break;
  399.  
  400.         case autoTrack:
  401.             break;
  402.     }
  403.  
  404.     return(0);
  405. }
  406.  
  407.  
  408.  
  409. /*****************************************************************************/
  410.  
  411.  
  412.  
  413. ControlHandle    CPICTNew(WindowPtr window, Rect *r, StringPtr title, Boolean vis, short val,
  414.                          short min, short max, short viewID, short refcon)
  415. {
  416.     WindowPtr        oldPort;
  417.     Rect            viewRct, rct;
  418.     Boolean            err;
  419.     ControlHandle    viewCtl;
  420.     unsigned long    variant;
  421.     PicHandle        pict;
  422.  
  423.     static ControlActionUPP    cupp;
  424.     static ControlDefUPP    cdefupp;
  425.  
  426.     GetPort(&oldPort);
  427.     SetPort(window);
  428.  
  429.     viewRct = *r;
  430.     viewCtl = nil;
  431.  
  432.     err = false;
  433.  
  434.     if (!gCDEF) {
  435.         gCDEF = (cdefRsrcJMPHndl)GetResource('CDEF', (viewID / 16));
  436.         if (gCDEF) {
  437.             if (!cdefupp) {
  438.                 cdefupp = NewControlDefProc(CPICTCtl);
  439.             }
  440.             (*gCDEF)->jmpAddress = (long)cdefupp;
  441.             if (TrapExists(_HWPriv))
  442.                 FlushInstructionCache();
  443.                     /* Make sure that instruction caches don't kill us. */
  444.         }
  445.         else err = true;
  446.     }
  447.  
  448.     if (!err) {
  449.         if (viewID & 0x04) {
  450.             viewID -= 0x04;
  451.             pict = (PicHandle)GetResource('PICT', refcon);
  452.             if (pict) {
  453.                 rct = (*pict)->picFrame;
  454.                 viewRct.right  = viewRct.left + (rct.right  - rct.left);
  455.                 viewRct.bottom = viewRct.top  + (rct.bottom - rct.top);
  456.             }
  457.         }
  458.         variant   = (viewID & 0x0F);
  459.         variant <<= 16;
  460.         viewCtl = NewControl(window, &viewRct, title, vis, val, min, max, viewID, (variant | refcon));
  461.         if (viewCtl) {
  462.             if (!cupp) cupp = NewControlActionProc(CPICTAction);
  463.             SetControlAction(viewCtl, cupp);
  464.         }
  465.         else
  466.             err = true;
  467.     }
  468.  
  469.     SetPort(oldPort);
  470.  
  471.     return(viewCtl);
  472. }
  473.  
  474.  
  475.  
  476. /*****************************************************************************/
  477.  
  478.  
  479.  
  480. ControlHandle    CPICTNext(WindowPtr window, ControlHandle ctl, short dir, Boolean justActive)
  481. {
  482.     ControlHandle    nextCtl, priorCtl;
  483.  
  484.     if (!window) return(nil);
  485.     if (!gCDEF)  return(nil);
  486.  
  487.     if (dir > 0) {
  488.         if (!ctl)
  489.             ctl = ((WindowPeek)window)->controlList;
  490.         else
  491.             ctl = (*ctl)->nextControl;
  492.         while (ctl) {
  493.             if ((!justActive) || ((*ctl)->contrlVis)) {
  494.                 if ((!justActive) || ((*ctl)->contrlHilite != 255)) {
  495.                     if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  496.                         return(ctl);
  497.                             /* The handle may be locked, which means that the hi-bit
  498.                             ** may be on, thus invalidating the compare.  Dereference the
  499.                             ** handles to get rid of this possibility. */
  500.                 }
  501.             }
  502.             ctl = (*ctl)->nextControl;
  503.         }
  504.         return(ctl);
  505.     }
  506.  
  507.     nextCtl = ((WindowPeek)window)->controlList;
  508.     for (priorCtl = nil; ;nextCtl = (*nextCtl)->nextControl) {
  509.         if ((!nextCtl) || (nextCtl == ctl)) return(priorCtl);
  510.         if ((!justActive) || ((*nextCtl)->contrlVis)) {
  511.             if ((!justActive) || ((*nextCtl)->contrlHilite != 255)) {
  512.                 if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  513.                     priorCtl = nextCtl;
  514.                         /* The handle may be locked, which means that the hi-bit
  515.                         ** may be on, thus invalidating the compare.  Dereference the
  516.                         ** handles to get rid of this possibility. */
  517.             }
  518.         }
  519.     }
  520. }
  521.  
  522.  
  523.  
  524. /*****************************************************************************/
  525.  
  526.  
  527.  
  528. Boolean    IsPICTCtl(ControlHandle ctl)
  529. {
  530.     if (ctl)
  531.         if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gCDEF))
  532.             return(true);
  533.                 /* The handle may be locked, which means that the hi-bit
  534.                 ** may be on, thus invalidating the compare.  Dereference the
  535.                 ** handles to get rid of this possibility. */
  536.     return(false);
  537. }
  538.  
  539.  
  540.  
  541. /*****************************************************************************/
  542.  
  543.  
  544.  
  545. static pascal void    CPICTAction(ControlHandle ctl, short part)
  546. {
  547.     static short    lastPart = 0;
  548.  
  549.     if (lastPart != part) {
  550.         lastPart = part;
  551.         CPICTCtl(0, ctl, drawCntl, part);
  552.     }
  553. }
  554.  
  555.  
  556.  
  557. /*****************************************************************************/
  558.  
  559.  
  560.  
  561. static pascal void    NoRect(GrafVerb verb, Rect *r)
  562. {
  563. #ifndef __MWERKS__
  564. #pragma unused (verb, r)
  565. #endif
  566. }
  567.  
  568.  
  569.  
  570. /*****************************************************************************/
  571.  
  572.  
  573.  
  574. static pascal PicHandle    GetPICT(ControlHandle ctl, short baseID, short id)
  575. {
  576.     Handle        dh;
  577.     PicHandle    pict;
  578.  
  579.     dh = (*ctl)->contrlData;
  580.     if (dh)
  581.         pict = (*(PicHandle **)dh)[id - baseID];
  582.     else
  583.         pict = (PicHandle)GetResource('PICT', id);
  584.  
  585.     return(pict);
  586. }
  587.  
  588.  
  589.  
  590.